﻿/////////////////////////////////////////////////////////////////
//
// Silverlight 5: 3D Physics using Balder and Jiglibx
// by Andy Beaulieu - http://www.andybeaulieu.com
//
// LICENSE: This code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ANY 
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS
// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
/////////////////////////////////////////////////////////////////
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Balder.Objects.Geometries;
using Microsoft.Xna.Framework;
using JigLibX.Physics;
using JigLibX.Collision;
using jlxg = JigLibX.Geometry;
using JigLibX.Geometry;
using JigLibX.Utils;

namespace Spritehand.Physics3D
{
    public class PhysicsHeightMap : IPhysicsObject
    {
        PhysicsSystem _world;
        Image _imgTerrain;
        Vector2 _shift;
        Balder.Objects.Geometries.Heightmap _heightMap;
        HeightMapInfo _heightMapInfo;

        public PhysicsHeightMap()
        {

        }

        public PhysicsHeightMap(PhysicsSystem world, Balder.Objects.Geometries.Heightmap heightMap, HeightMapInfo heightMapInfo, Vector2 shift)
        {
            Balder.Math.Dimension dimension = new Balder.Math.Dimension();
            _heightMap = heightMap;
            _heightMapInfo = heightMapInfo;

            _shift = shift;
            InitPhysics(_world);
        }

          private Body _physicsBody;
        public Body PhysicsBody()
        {
            return _physicsBody;
        }

        private CollisionSkin _skin;
        public CollisionSkin Skin
        {
            get
            {
                return _skin;
            }
        }

        public bool Immovable
        {
            get
            {
                return _physicsBody.Immovable;
            }
            set
            {
                _physicsBody.Immovable = value;
            }
        }

        public void InitPhysics(PhysicsSystem world)
        {
            _world = world;

         
            _physicsBody = new Body(); // just a dummy. The PhysicObject uses its position to get the draw pos
            _skin = new CollisionSkin(null);
            _physicsBody.CollisionSkin = _skin;


            Array2D field = new Array2D(_heightMap.LengthSegments, _heightMap.HeightSegments);

            for (int x = 0; x < _heightMap.LengthSegments; x++)
            {
                for (int z = 0; z < _heightMap.HeightSegments; z++)
                {
                    field.SetAt(x, z, _heightMapInfo.heights[x, z]);
                }
            }

            // move the body. The body (because its not connected to the collision
            // skin) is just a dummy. But the base class shoudl know where to
            // draw the model.
            _physicsBody.MoveTo(new Vector3(_shift.X, 0, _shift.Y), Microsoft.Xna.Framework.Matrix.Identity);

            _skin.AddPrimitive(new JigLibX.Geometry.Heightmap(field, _shift.X, _shift.Y, 1, 1), new MaterialProperties(0.7f, 0.7f, 0.6f));

            PhysicsSystem.CurrentPhysicsSystem.CollisionSystem.AddCollisionSkin(_skin);



        }

        public void Draw()
        {

            if (_skin == null)
                return;

            //this.Position = Utils.VectorXnaToBalder(_skin.NewPosition);

            //Microsoft.Xna.Framework.Matrix matrixSrc = _physicsBody.CollisionSkin.GetPrimitiveLocal(0).Transform.Orientation * _physicsBody.Orientation;

            //Balder.Math.Matrix matrix = Utils.MatrixXnaToBalder(matrixSrc);

            //this.World = matrix;

        }

        private Vector3 SetMass(float mass)
        {
            PrimitiveProperties primitiveProperties = new PrimitiveProperties(
                PrimitiveProperties.MassDistributionEnum.Solid,
                PrimitiveProperties.MassTypeEnum.Mass, mass);

            float junk;
            Vector3 com;
            Microsoft.Xna.Framework.Matrix it;
            Microsoft.Xna.Framework.Matrix itCoM;

            Skin.GetMassProperties(primitiveProperties, out junk, out com, out it, out itCoM);

            _physicsBody.BodyInertia = itCoM;
            _physicsBody.Mass = junk;

            return com;
        }

    }
}
